package com.googlecode.dgwt.client.dojo.impl;

import java.util.Map;

import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.googlecode.dgwt.client.dojo.string.RegExp;
import com.googlecode.dgwt.client.dojo.string.RegExpResult;
import com.googlecode.dgwt.client.dojo.util.JsUtil;
import com.googlecode.dgwt.client.dojo.util.StringMap;


/**
 * This is an adapted version of Dojo, built for deployment on GWT. 
 * To get a JavaScript-based version, please visit:
 *     
 *        http://dojotoolkit.org
 *
 * for documentation and information on getting the source.
 * 
 * @author    Wellington Tadeu dos Santos
 * @since    DGWT v0.01
 */
public class NavigatorImpl {
    
    
    /**
     * Version as a Number if client is Adobe AIR. 
     */
    public final float isAIR;

    
    /**
     * Version as a Number if client is Chrome browser. 
     */
    public final float isChrome;
    
    
    /**
     * Version as a Number if client is FireFox.
     * Corresponds to major detected FireFox version (1.5, 2, 3, etc.)
     */
    public final float isFF;
    
    
        /**
         * Version as a Number if client is a Gecko-based browser. 
         * Corresponds to major detected version.
         */
    public final float isGecko;

    
    /**
     * Version as a Number if client is MSIE(PC). 
     * Corresponds to major detected IE version (6, 7, 8, etc.)
     */
    public final float isIE;

    
    /**
     * Version as a Number if client is MSIE(PC). 
     * Corresponds to major detected IE version < 6 
     * or running in QuirksMode emulation on IE.
     */
    public final float isIEQuirks;
    
    
    /**
     * Version as a Number if client is Safari and iPhone.
     */
    public final float isIPhone;
    

    /**
     * Version as a Number if client is Safari and iPod.
     */
    public final float isIPod;

    
    /**
     * Version as a Number if client is a KHTML browser. 
     * Corresponds to major detected version.
     */
    public final float isKhtml;

    
        /**
         * Version as a Number if client is a Mozilla-based browser (Firefox, SeaMonkey). 
         * Corresponds to major detected version.
         */
        public final float isMozilla;

        
    /**
     * Version as a Number if client is Opera.
     * Corresponds to major detected version.
     */
    public final float isOpera;
    
    
    /**
     * Value set to 1 if running in QuirksMode emulation.
     */
    public final float isQuirks;
    
    
    /**
     * Version as a Number if client is Safari.
     */
    public final float isSafari;

    
    /**
     * Version as a Number if client is a WebKit-derived browser (Konqueror, Safari, Chrome, etc.).
     */
    public final float isWebKit;

    
    
    public NavigatorImpl(){
        
        final Element document = Document.get().<Element>cast();
        final String dua = getNavigatorProperty("userAgent");
        final String dav = getNavigatorProperty("appVersion");        
        float tv = JsUtil.parseFloat(dav);
        
        
        if (dua.indexOf("Opera") >= 0) {
            this.isOpera = tv;
        } else {
            this.isOpera = 0;
        }
        
        if (dua.indexOf("AdobeAIR") >= 0) {
            this.isAIR = 1;
        } else {
            this.isAIR = 0;
        }
        
        if (dav.indexOf("Konqueror") >= 0) {
            this.isKhtml = tv;
        } else {
            this.isKhtml = 0;
        }
        
        this.isWebKit = getFloat(dua.split("WebKit/"), 1);
        this.isChrome = getFloat(dua.split("Chrome/"), 1);
        
        int ws = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"));
        if (ws > 0 && !this.isChrome()) {
            
            this.isSafari = JsUtil.or(
                getFloat(dav.split("Version/"), 1),
                JsUtil.parseFloat(dav.substring(ws + 7)) > 419.3 ? 3 : 2
            );

            if (this.isSafari()){
                this.isIPod = (dua.indexOf("iPod") != -1) ? this.isSafari : 0;
                this.isIPhone = (dua.indexOf("iPhone") != -1) ? this.isSafari : 0;
            } else {
                this.isIPod = 0;
                this.isIPhone = 0;
            }
        } else {
            this.isSafari = 0;
            this.isIPhone = 0;
            this.isIPod = 0;
        }
        
        if (dua.indexOf("Gecko") >= 0) {
            RegExpResult result = RegExp.create("rv:([0-9]+)(\\.[0-9]+)").exec(dua);
            float rv = 0;
            
            if (result != null 
                    && result.length() > 1) {
                rv = JsUtil.parseFloat(result.get(1) + JsUtil.<String>or(result.get(2), ""));
            }
            
            if (!this.isKhtml() && !this.isWebKit()){
                this.isMozilla = tv;
            } else {
                this.isMozilla = 0;
            }
            
            if (rv <= 0){
                rv = 0.01f;
            }            
            this.isGecko = rv;
        } else {
            this.isGecko = 0;
            this.isMozilla = 0;
        }

        if (this.isGecko()) {
            this.isFF = JsUtil.or(
                getFloat(dua.split("Firefox/"), 1),
                getFloat(dua.split("Minefield/"), 1),
                getFloat(dua.split("Shiretoko/"), 1)
            );
        } else {
            this.isFF = 0;
        }
        
        if (document.getPropertyBoolean("all") && !this.isOpera()) {
            float isIE = JsUtil.parseFloat(dav.split("MSIE ")[1]);
            
            //document.documentMode of 5 means quirks mode.
            if (isIE >= 8 && document.getPropertyInt("documentMode") != 5){
                isIE = document.getPropertyInt("documentMode");
            }
            
            this.isIE = isIE;
        } else {
            this.isIE = 0;
        }        

        String cm = document.getPropertyString("compatMode");
        
        this.isQuirks = ("BackCompat".equals(cm) || "QuirksMode".equals(cm) || this.isIE < 6) ? 1F : 0;
        this.isIEQuirks = this.isQuirks() ? this.isIE : 0;
    }
    
    
    private native String getNavigatorProperty(String name) /*-{
        return $wnd.navigator[name];
    }-*/;


    private float getFloat(String[] vet, int i){
        return i < vet.length ? JsUtil.parseFloat(vet[i]) : 0;
    }
    
    
    /**
     * Gets all version fields as a Map
     * @return versions
     */
    public Map<String, Float> toMap(){
        Map<String, Float> items = new StringMap<Float>();
        items.put("isAIR", isAIR);
        items.put("isChrome", isChrome);
        items.put("isFF", isFF);
        items.put("isGecko", isGecko);
        items.put("isIE", isIE);
        items.put("isIEQuirks", isIEQuirks() ? 1F : 0F);
        items.put("isIPhone", isIPhone() ? 1F : 0F);
        items.put("isIPod", isIPod() ? 1F : 0F);
        items.put("isKhtml", isKhtml);
        items.put("isMozilla", isMozilla);
        items.put("isOpera", isOpera);
        items.put("isSafari", isSafari);
        items.put("isWebKit", isWebKit);
        
        // FIXME for (Entry<String, Float> item : items.entrySet())
          //  Console.log(item.getKey() + "=" + item.getValue());
        
        return items;
    }
    
    
    /**
     * @return True if the client is AIR
     */
    public final boolean isAIR(){
        return isAIR > 0;
    }

    /**
     * @return True if the client is a web-browser
     */
    public final boolean isBrowser() {
        return true;
    }
    
    /**
     * @return True if the client is Chrome
     */
    public final boolean isChrome() {
        return isChrome > 0;
    }

    /**
     * @return True if the client is IE
     */
    public final boolean isIE(){
        return isIE > 0;
    }
    
    /**
     * @return True if the client is IE in Quirks Mode
     */
    public final boolean isIEQuirks(){
        return isIEQuirks > 0;
    }
    
    /**
     * @return True if the client is IPhone
     */
    public final boolean isIPhone() {
        return isIPhone > 0;
    }

    /**
     * @return True if the client is IPod
     */
    public final boolean isIPod() {
        return isIPod > 0;
    }

    /**
     * @return True if the client is FireFox
     */
    public final boolean isFF(){
        return isFF > 0;
    }
    
    /**
     * @return True if the client is Gecko
     */
    public final boolean isGecko() {
        return isGecko > 0;
    }

    /**
     * @return True if the client is Khtml
     */
    public final boolean isKhtml(){
        return isKhtml > 0;
    }
    
    /**
     * @return True if the client is Mozilla
     */
    public final boolean isMozilla(){
        return isMozilla > 0;
    }
    
    /**
     * @return True if the client is Opera
     */
    public final boolean isOpera(){
        return isOpera > 0;
    }
    
    /**
     * @return True if the client is Safari
     */
    public final boolean isSafari(){
        return isSafari > 0;
    }

    /**
     * @return True if the client is running in Quirks Mode
     */
    public final boolean isQuirks(){
        return isQuirks > 0;
    }
    
    /**
     * @return True if the client is WebKit
     */
    public final boolean isWebKit() {
        return isWebKit > 0;
    }

}
